home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1991
/
01
/
ems.asm
< prev
next >
Wrap
Assembly Source File
|
1990-10-31
|
7KB
|
367 lines
title expanded memory interace
include asm.inc
public ems_exchange
public ems_in
public ems_out
EMS_MAX equ 1024 ; (must be multiple of 8)
NULL_EMS equ 0
move_source_dest_struct struc ; from "official" LIM EMS 4.0 Spec - page 3-87
region_length dd ?
source_memory_type db ?
source_handle dw ?
source_initial_offset dw ?
source_initial_seg_page dw ?
dest_memory_type db ?
dest_handle dw ?
dest_initial_offset dw ?
dest_initial_seg_page dw ?
move_source_dest_struct ends
XIB segment word public 'DATA' ; enable exit intercept during
XIB ends ; intialization
XI segment word public 'DATA'
dw enable_exit_intercept
XI ends
XIE segment word public 'DATA'
XIE ends
XCB segment word public 'DATA' ; always release EMS on termination
XCB ends
XC segment word public 'DATA'
dw ems_close
XC ends
XCE segment word public 'DATA'
XCE ends
.data?
ems_struc move_source_dest_struct <>
ems_count dw ? ; number of allocated pages
ems_handle dw ?
ems_ecount dw ?
ems_icount dw ?
ems_ocount dw ?
ems_version db ?
ems_flag db ?
ems_bits db EMS_MAX/8 dup(?)
.const
ertx_ems_index db 'Bad EMS index',0
ertx_ems_error db 'Error in EMS',0
.code
extn set_strerror,get_vector,enable_exit_intercept
;; do ems function
;
; exit Cf if error (sets error string)
;
do_ems_function proc
int 67h
or ah,ah
jnz def1 ; if EMS error
ret
def1: lea ax,ertx_ems_error ; *Error in EMS*
jmp set_strerror
do_ems_function endp
;; do ems raw
;
; exit Cf if error (doesn't set error string)
;
do_ems_raw proc
int 67h
or ah,ah
jnz der1 ; if EMS error
ret
der1: stc
ret
do_ems_raw endp
;; ems close
;
; uses AX,DX
;
ems_close proc
movx dx,NULL_EMS
xchg dx,ems_handle[bp]
cmpx dx,NULL_EMS
je ecl1 ;\ if EMS not in use
mov ah,45h ; deallocate pages
call do_ems_function
ecl1: ret
ems_close endp
;; ems exchange
;
; entry AX page index (1..n)
; ES:DI destination
; exit Cf if bad block or EMS error
; uses AX
;
ems_exchange proc
pushm si,ds ; adjust and set EMS page index
dec ax
mov ems_struc.dest_initial_seg_page[bp],ax
call read_move_struc
jc eex1 ; if no EMS
mov dest_handle[si],ax
movx ax,0 ; fill in move structure
mov source_memory_type[si],al
mov source_handle[si],ax
mov source_initial_offset[si],di
mov source_initial_seg_page[si],es
mov dest_memory_type[si],1
mov dest_initial_offset[si],ax
mov ax,5701h ; exchange RAM and EMS
call do_ems_function
inc ems_ecount[bp]
eex1: popm ds,si
ret
ems_exchange endp
;; ems in
;
; entry AX block index (1..n)
; ES:DI destination (no transfer if NULL)
; exit Cf if bad block or EMS error
; uses AX
;
ems_in proc
pushm cx,si,ds
dec ax ; clear index bit
js ein2 ; if bad swap index (cannot be -)
mov si,ax
mov cl,3 ; (divide bit number by 8 to select
shr si,cl ; byte)
mov cl,al ; (use the 3 least significant bits
and cl,7 ; to rotate a mask)
mov ch,10000000b
ror ch,cl
test ems_bits[bp+si],ch
jz ein2 ; if bad EMS index
xor ems_bits[bp+si],ch ; (Cf=0)
mov cx,es ; do not read EMS file if NULL output
jcxz ein1 ; if NULL destination (Cf==0)
; set structure for move memory region
mov ems_struc.source_initial_seg_page[bp],ax
call read_move_struc
jc ein1 ; if no EMS
mov source_handle[si],ax
movx ax,0
mov source_memory_type[si],1
mov source_initial_offset[si],ax
mov dest_memory_type[si],al
mov dest_handle[si],ax
mov dest_initial_offset[si],di
mov dest_initial_seg_page[si],es
mov ax,5700h ; move from EMS to RAM
call do_ems_function
inc ems_icount[bp]
ein1: popm ds,si,cx
ret
ein2: lea ax,ertx_ems_index ; *Bad EMS index*
call set_strerror
jmp ein1
ems_in endp
;; ems out
;
; entry ES:DI source
; exit AX block index (1..n)
; Cf if EMS full or EMS error
;
ems_out proc
pushm cx,si,ds
call read_move_struc ; set structure for move memory region
jc eou2 ; if no EMS
mov dest_handle[si],ax
movx ax,0
mov source_memory_type[si],al
mov source_handle[si],ax
mov source_initial_offset[si],di
mov source_initial_seg_page[si],es
mov dest_memory_type[si],1
mov dest_initial_offset[si],ax
call get_ems_index ; select next free EMS block
jc eou2 ; if EMS bit map full
mov dest_initial_seg_page[si],ax
mov cx,ax
cmp ax,ems_count[bp] ; check EMS allocation
jb eou1 ; if enough EMS pages allocated
call realloc_more_ems ; else get more ESM from driver
jc eou2 ; if EMS full
eou1: mov ax,5700h ; move from EMS to RAM
call do_ems_function
inc ems_ocount[bp]
mov ax,cx ; return EMS index (1..MAX)
inc ax
eou2: popm ds,si,cx
ret
ems_out endp
;; get ems index
;
; exit AX ems index (0..MAX-1)
; Cf if no (more) EMS
; uses CX
;
get_ems_index proc
push si
mov al,1
mov cx,EMS_MAX
lea si,ems_bits-1
even ; search ems bits for first free index
gei1: ror al,1
adc si,ZER0
test al,[bp+si]
loopnz gei1
stc
jnz gei2 ; if EMS full
or [bp+si],al
mov ax,EMS_MAX-1
sub ax,cx
gei2: pop si
ret
get_ems_index endp
;; get ems version
;
; exit AL EMS version or 0 if no EMS
; uses SI,DS
;
get_ems_version proc
mov al,67h
call get_vector
mov si,0Ah
lodsw
cmp ax,'ME'
jne gev1 ; if no EMS
lodsw
cmp ax,'XM'
jne gev1 ; if no EMS
lodsw
cmp ax,'XX'
jne gev1 ; if no EMS
lodsw
cmp ax,'0X'
jne gev1 ; if no EMS
mov ah,46h ; get EMS version
call do_ems_function
jnc gev2
gev1: movx ax,0
stc
gev2: ret
get_ems_version endp
;; read move struc
;
; exit AX EMS handle
; DS:SI "move source dest" structure
; Cf if no EMS
; note all members set to zero except region_length
;
read_move_struc proc
mov ax,ems_handle[bp]
cmpx ax,NULL_EMS
je rms2 ; if no ems
rms1: movx ds,DGROUP_SEGMENT
lea si,ems_struc
mov wptr region_length[si],BLOCK_SIZE
mov wptr region_length[si+2],ZER0
clc
ret
rms2: mov al,-1
xchg al,ems_flag[bp]
add al,-1
jc rms4 ; if previous attempt failed
call get_ems_version
mov ems_version[bp],al
cmp al,40h
jb rms4 ; if EMS missing or out of date
rms3: mov ah,43h ; get EMS handle
pushm bx,dx
mov bx,1 ; allocate just 1 page
call do_ems_raw
mov ax,dx
popm dx,bx
jc rms4 ; if no EMS available (probably)
mov ems_handle[bp],ax
mov ems_count[bp],1
cmpx ax,NULL_EMS ; reject a zero EMS handle (Cf=0)
je rms3 ; if bad handle
jmp rms1
rms4: ret
read_move_struc endp
;; realloc more ems
;
; exit Cf if no more EMS
; uses AX
;
realloc_more_ems proc
pushm bx,dx
mov bx,ems_count[bp]
inc bx
mov dx,ems_handle[bp]
mov ah,51h
call do_ems_raw
jc rme1 ; if out of EMS
mov ems_count[bp],bx
rme1: popm dx,bx
ret
realloc_more_ems endp
end